From 5c9643b6ebe2adda42e60255954748334bdb3c2c Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Thu, 25 Jul 2019 17:50:31 -0400 Subject: [PATCH] vulkan: implement subpixel positioning Pass the glyph position into the glyph caching functions, not just the glyph index. This allows us to cache different images for different subpixel positions. --- gsk/vulkan/gskvulkancolortextpipeline.c | 11 ++++++++--- gsk/vulkan/gskvulkanglyphcache.c | 25 +++++++++++++++++++++---- gsk/vulkan/gskvulkanglyphcacheprivate.h | 3 +++ gsk/vulkan/gskvulkanrenderer.c | 24 ++++++++++++++---------- gsk/vulkan/gskvulkanrendererprivate.h | 4 ++++ gsk/vulkan/gskvulkanrenderpass.c | 11 ++++++++++- gsk/vulkan/gskvulkantextpipeline.c | 11 ++++++++--- 7 files changed, 68 insertions(+), 21 deletions(-) diff --git a/gsk/vulkan/gskvulkancolortextpipeline.c b/gsk/vulkan/gskvulkancolortextpipeline.c index a7b0ad39a7..5ffe62adcc 100644 --- a/gsk/vulkan/gskvulkancolortextpipeline.c +++ b/gsk/vulkan/gskvulkancolortextpipeline.c @@ -119,12 +119,17 @@ gsk_vulkan_color_text_pipeline_collect_vertex_data (GskVulkanColorTextPipeline * if (gi->glyph != PANGO_GLYPH_EMPTY) { - double cx = (double)(x_position + gi->geometry.x_offset) / PANGO_SCALE; - double cy = (double)(gi->geometry.y_offset) / PANGO_SCALE; + double cx = (x_position + gi->geometry.x_offset) / PANGO_SCALE; + double cy = gi->geometry.y_offset / PANGO_SCALE; GskVulkanColorTextInstance *instance = &instances[count]; GskVulkanCachedGlyph *glyph; - glyph = gsk_vulkan_renderer_get_cached_glyph (renderer, font, gi->glyph, scale); + glyph = gsk_vulkan_renderer_get_cached_glyph (renderer, + font, + gi->glyph, + x_position + gi->geometry.x_offset, + gi->geometry.y_offset, + scale); instance->tex_rect[0] = glyph->tx; instance->tex_rect[1] = glyph->ty; diff --git a/gsk/vulkan/gskvulkanglyphcache.c b/gsk/vulkan/gskvulkanglyphcache.c index ce3a6947e6..830b4d70c9 100644 --- a/gsk/vulkan/gskvulkanglyphcache.c +++ b/gsk/vulkan/gskvulkanglyphcache.c @@ -115,6 +115,8 @@ gsk_vulkan_glyph_cache_class_init (GskVulkanGlyphCacheClass *klass) typedef struct { PangoFont *font; PangoGlyph glyph; + guint xshift; + guint yshift; guint scale; /* times 1024 */ } GlyphCacheKey; @@ -126,6 +128,8 @@ glyph_cache_equal (gconstpointer v1, gconstpointer v2) return key1->font == key2->font && key1->glyph == key2->glyph && + key1->xshift == key2->xshift && + key1->yshift == key2->yshift && key1->scale == key2->scale; } @@ -134,7 +138,7 @@ glyph_cache_hash (gconstpointer v) { const GlyphCacheKey *key = v; - return GPOINTER_TO_UINT (key->font) ^ key->glyph ^ key->scale; + return GPOINTER_TO_UINT (key->font) ^ key->glyph ^ (key->xshift << 24) ^ (key->yshift << 26) ^ key->scale; } static void @@ -267,10 +271,10 @@ render_glyph (Atlas *atlas, gi.glyph = key->glyph; gi.geometry.width = value->draw_width * 1024; if (key->glyph & PANGO_GLYPH_UNKNOWN_FLAG) - gi.geometry.x_offset = 0; + gi.geometry.x_offset = key->xshift * 256; else - gi.geometry.x_offset = - value->draw_x * 1024; - gi.geometry.y_offset = - value->draw_y * 1024; + gi.geometry.x_offset = key->xshift * 256 - value->draw_x * 1024; + gi.geometry.y_offset = key->yshift * 256 - value->draw_y * 1024; glyphs.num_glyphs = 1; glyphs.glyphs = &gi; @@ -328,18 +332,29 @@ gsk_vulkan_glyph_cache_new (GskRenderer *renderer, return cache; } +#define PHASE(x) ((x % PANGO_SCALE) * 4 / PANGO_SCALE) + GskVulkanCachedGlyph * gsk_vulkan_glyph_cache_lookup (GskVulkanGlyphCache *cache, gboolean create, PangoFont *font, PangoGlyph glyph, + int x, + int y, float scale) { GlyphCacheKey lookup_key; GskVulkanCachedGlyph *value; + guint xshift; + guint yshift; + + xshift = PHASE (x); + yshift = PHASE (y); lookup_key.font = font; lookup_key.glyph = glyph; + lookup_key.xshift = xshift; + lookup_key.yshift = yshift; lookup_key.scale = (guint)(scale * 1024); value = g_hash_table_lookup (cache->hash_table, &lookup_key); @@ -374,6 +389,8 @@ gsk_vulkan_glyph_cache_lookup (GskVulkanGlyphCache *cache, key->font = g_object_ref (font); key->glyph = glyph; + key->xshift = xshift; + key->yshift = yshift; key->scale = (guint)(scale * 1024); if (ink_rect.width > 0 && ink_rect.height > 0) diff --git a/gsk/vulkan/gskvulkanglyphcacheprivate.h b/gsk/vulkan/gskvulkanglyphcacheprivate.h index b566e5b9bc..b31711fe6d 100644 --- a/gsk/vulkan/gskvulkanglyphcacheprivate.h +++ b/gsk/vulkan/gskvulkanglyphcacheprivate.h @@ -22,6 +22,9 @@ GskVulkanCachedGlyph *gsk_vulkan_glyph_cache_lookup (GskVulkanGlyphCache gboolean create, PangoFont *font, PangoGlyph glyph, + int x, + int y, + float scale); void gsk_vulkan_glyph_cache_begin_frame (GskVulkanGlyphCache *cache); diff --git a/gsk/vulkan/gskvulkanrenderer.c b/gsk/vulkan/gskvulkanrenderer.c index 6fc59758c6..867f51b5d6 100644 --- a/gsk/vulkan/gskvulkanrenderer.c +++ b/gsk/vulkan/gskvulkanrenderer.c @@ -362,15 +362,6 @@ gsk_vulkan_renderer_ref_texture_image (GskVulkanRenderer *self, return image; } -guint -gsk_vulkan_renderer_cache_glyph (GskVulkanRenderer *self, - PangoFont *font, - PangoGlyph glyph, - float scale) -{ - return gsk_vulkan_glyph_cache_lookup (self->glyph_cache, TRUE, font, glyph, scale)->texture_index; -} - GskVulkanImage * gsk_vulkan_renderer_ref_glyph_image (GskVulkanRenderer *self, GskVulkanUploader *uploader, @@ -379,13 +370,26 @@ gsk_vulkan_renderer_ref_glyph_image (GskVulkanRenderer *self, return g_object_ref (gsk_vulkan_glyph_cache_get_glyph_image (self->glyph_cache, uploader, index)); } +guint +gsk_vulkan_renderer_cache_glyph (GskVulkanRenderer *self, + PangoFont *font, + PangoGlyph glyph, + int x, + int y, + float scale) +{ + return gsk_vulkan_glyph_cache_lookup (self->glyph_cache, TRUE, font, glyph, x, y, scale)->texture_index; +} + GskVulkanCachedGlyph * gsk_vulkan_renderer_get_cached_glyph (GskVulkanRenderer *self, PangoFont *font, PangoGlyph glyph, + int x, + int y, float scale) { - return gsk_vulkan_glyph_cache_lookup (self->glyph_cache, FALSE, font, glyph, scale); + return gsk_vulkan_glyph_cache_lookup (self->glyph_cache, FALSE, font, glyph, x, y, scale); } /** diff --git a/gsk/vulkan/gskvulkanrendererprivate.h b/gsk/vulkan/gskvulkanrendererprivate.h index d492a85b1f..eca34ccabd 100644 --- a/gsk/vulkan/gskvulkanrendererprivate.h +++ b/gsk/vulkan/gskvulkanrendererprivate.h @@ -30,6 +30,8 @@ typedef struct guint gsk_vulkan_renderer_cache_glyph (GskVulkanRenderer *renderer, PangoFont *font, PangoGlyph glyph, + int x, + int y, float scale); GskVulkanImage * gsk_vulkan_renderer_ref_glyph_image (GskVulkanRenderer *self, @@ -39,6 +41,8 @@ GskVulkanImage * gsk_vulkan_renderer_ref_glyph_image (GskVulkanRenderer * GskVulkanCachedGlyph * gsk_vulkan_renderer_get_cached_glyph (GskVulkanRenderer *self, PangoFont *font, PangoGlyph glyph, + int x, + int y, float scale); diff --git a/gsk/vulkan/gskvulkanrenderpass.c b/gsk/vulkan/gskvulkanrenderpass.c index 55f96456a8..00fd658d8b 100644 --- a/gsk/vulkan/gskvulkanrenderpass.c +++ b/gsk/vulkan/gskvulkanrenderpass.c @@ -370,6 +370,7 @@ gsk_vulkan_render_pass_add_node (GskVulkanRenderPass *self, int i; guint count; guint texture_index; + gint x_position; GskVulkanRenderer *renderer = GSK_VULKAN_RENDERER (gsk_vulkan_render_get_renderer (render)); if (font_has_color_glyphs (font)) @@ -402,11 +403,17 @@ gsk_vulkan_render_pass_add_node (GskVulkanRenderPass *self, op.text.texture_index = G_MAXUINT; op.text.scale = self->scale_factor; + x_position = 0; for (i = 0, count = 0; i < num_glyphs; i++) { const PangoGlyphInfo *gi = &glyphs[i]; - texture_index = gsk_vulkan_renderer_cache_glyph (renderer, (PangoFont *)font, gi->glyph, op.text.scale); + texture_index = gsk_vulkan_renderer_cache_glyph (renderer, + (PangoFont *)font, + gi->glyph, + x_position + gi->geometry.x_offset, + gi->geometry.y_offset, + op.text.scale); if (op.text.texture_index == G_MAXUINT) op.text.texture_index = texture_index; if (texture_index != op.text.texture_index) @@ -421,6 +428,8 @@ gsk_vulkan_render_pass_add_node (GskVulkanRenderPass *self, } else count++; + + x_position += gi->geometry.width; } if (op.text.texture_index != G_MAXUINT && count != 0) diff --git a/gsk/vulkan/gskvulkantextpipeline.c b/gsk/vulkan/gskvulkantextpipeline.c index 7cd85c5d9a..9544c6a7c7 100644 --- a/gsk/vulkan/gskvulkantextpipeline.c +++ b/gsk/vulkan/gskvulkantextpipeline.c @@ -127,12 +127,17 @@ gsk_vulkan_text_pipeline_collect_vertex_data (GskVulkanTextPipeline *pipeline, if (gi->glyph != PANGO_GLYPH_EMPTY) { - double cx = (double)(x_position + gi->geometry.x_offset) / PANGO_SCALE; - double cy = (double)(gi->geometry.y_offset) / PANGO_SCALE; + double cx = (x_position + gi->geometry.x_offset) / PANGO_SCALE; + double cy = gi->geometry.y_offset / PANGO_SCALE; GskVulkanTextInstance *instance = &instances[count]; GskVulkanCachedGlyph *glyph; - glyph = gsk_vulkan_renderer_get_cached_glyph (renderer, font, gi->glyph, scale); + glyph = gsk_vulkan_renderer_get_cached_glyph (renderer, + font, + gi->glyph, + x_position + gi->geometry.x_offset, + gi->geometry.y_offset, + scale); instance->tex_rect[0] = glyph->tx; instance->tex_rect[1] = glyph->ty; -- 2.30.2